package com.hsj.springai.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class MethodExporterAspect {

    //只有带着@MethodLog注解的方法才会被增强
    @Around("@annotation(com.hsj.springai.config.MethodLog)")
    public Object methodExporter(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object retValue = null;
        long startTime = System.currentTimeMillis();
        log.info("@Around 环绕通知开始aaaa");
        retValue = proceedingJoinPoint.proceed();
        long endTime = System.currentTimeMillis();
        long costTime = endTime - startTime;
        //获得重载后的方法名
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        //确定方法上面是否配置了@MethodLog的注解
        MethodLog annotation = method.getAnnotation(MethodLog.class);
        if (annotation != null) {
            //StringBuffer 用于存放方法参数名和参数值
            StringBuffer jsonInputParam = new StringBuffer();
            //获取方法参数
            Object[] args = proceedingJoinPoint.getArgs();
            //创建一个解析器 去解析某个方法
            DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
            //将方法丢入解析器
            String[] parameterNames = discoverer.getParameterNames(method);
            //将解析出来的参数名遍历 和 参数值 拼接
            for (int i = 0; i < parameterNames.length; i++) {
                jsonInputParam.append(parameterNames[i] + "\t" + args[i].toString() + ";");
            }
            //将返回结果retValue序列化
            String jsonResult = null;
            if (retValue != null) {
                jsonResult = new ObjectMapper().writeValueAsString(retValue);
            } else {
                jsonResult = "null";
            }


            log.info("方法分析并上报" +
                    "\n类名/方法名" + proceedingJoinPoint.getTarget().getClass().getName() + "." + ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod().getName() +
                    "\n执行耗时" + costTime + "毫秒" +
                    "\n输入参数" + jsonInputParam +
                    "\n返回结果" + jsonResult +
                    "\n 结束"
            );

        log.info("@Around 环绕通知开始bbbb");
        }
        return retValue;
    }
}
